package com.wk.springboot.spring.beanPostProcessor;

import lombok.SneakyThrows;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Vector;

/**
 * description:
 *
 * <pre>
 *      <strong>概念</strong>
 *      允许自定义修改新bean实例的Factory钩子，例如检查标记接口或用代理包装它们。
 *
 *      ApplicationContexts可以在bean定义中自动检测BeanPostProcessor bean，并将它们应用于随后创建的任何bean。
 *      普通bean工厂允许对后处理器进行编程注册，应用于通过该工厂创建的所有bean。
 *
 *      通常，通过标记接口等填充bean的后处理程序将实现{@link#postProcessBeforeInitialization}，
 *      而使用代理包装bean的后处理器通常会实现{@link}postProcessAfterInitialization}。
 *
 *      测试{@link Person}
 *      得到结果如下：
           对beanName = person属性填充
           person.........construct
           person.......afterPropertiesSet
           person.........initMethod
           对beanName = person生成代理对象

        这样的话就可以对bean的创建做一些拦截操作
 *
 *  </pre>
 * date 2020-12-06 16:25
 *
 * @author Administrator
 * @version 1.0
 */
@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

    private BeanFactory beanFactory;

    /**
     * 这个方法一般都是对bean做一些属性的填充。如在ApplicationAwareBeanPostProcessor中就是获取applicationContext
     * 在(like InitializingBean's {@code afterPropertiesSet} or a custom init-method)之前执行
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("对beanName = " + beanName + "属性填充");
        return bean;
    }

    /**
     * 对象做代理封装，AbstractAutoProxyCreator#postProcessAfterInitialization就是用来做代理对象的并把代理对象返回。
     * 在(like InitializingBean's {@code afterPropertiesSet} or a custom init-method)之后执行
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @SneakyThrows
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("对beanName = " + beanName + "生成代理对象");
        Class person = Class.forName(beanName);
        return bean;
    }

    /**
     * 这个在三种生命周期中最后一个执行的
     * @return
     */
    @Bean(initMethod = "initMethod")
    public Person person(){
        return new Person();
    }

    @Test
    public void test(){

    }

}
